package graphicalUserInterface;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;

import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wb.swt.SWTResourceManager;
import org.xml.sax.SAXException;

import settings.MasterController;

import entity.CashFlow;
import entity.CashFlow.Period;
import entity.Category;
import entity.Expense;
import entity.Goal;
import entity.Income;
import entity.Source;
import exception.IllegalInput;

//@author U096819H
public class AddItem extends Dialog {

	protected Object result;
	protected Shell shell;
	private Composite formExpense;
	private Composite formIncome;
	private Composite formGoal;

	// @author U096819H
	public AddItem(Shell parent, int style) {
		super(parent, style);
		setText("Add New Item");
	}

	// @author U096819H
	public void open(final MasterController mc) {
		createContents(mc);
		shell.open();
		shell.layout();
		Display display = getParent().getDisplay();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	// @author U096819H
	private void createContents(final MasterController mc) {
		shell = new Shell(getParent(), getStyle());
		shell.setSize(400, 310);
		shell.setText(getText());
		shell.setLayout(new FormLayout());

		// UI element definitions
		Composite menuHolder = new Composite(shell, SWT.NONE);
		Label lblMenu = new Label(menuHolder, SWT.NONE);
		final Combo menuCombo = new Combo(menuHolder, SWT.READ_ONLY);

		// Composite:: Menu Holder
		FormData fd_menuHolder = new FormData();
		fd_menuHolder.bottom = new FormAttachment(0, 48);
		fd_menuHolder.right = new FormAttachment(0, 384);
		fd_menuHolder.top = new FormAttachment(0, 10);
		fd_menuHolder.left = new FormAttachment(0, 10);
		menuHolder.setLayoutData(fd_menuHolder);
		menuHolder.setLayout(new GridLayout(2, false));

		formExpense = new Composite(shell, SWT.NONE);
		formExpense.setLayout(new GridLayout(4, false));
		FormData fd_formExpense = new FormData();
		fd_formExpense.top = new FormAttachment(menuHolder, 13);
		fd_formExpense.bottom = new FormAttachment(100, -10);
		fd_formExpense.left = new FormAttachment(0, 10);
		fd_formExpense.right = new FormAttachment(0, 384);
		formExpense.setLayoutData(fd_formExpense);

		formIncome = new Composite(shell, SWT.NONE);
		formIncome.setLayout(new GridLayout(4, false));
		FormData fd_income_composite = new FormData();
		fd_income_composite.top = new FormAttachment(menuHolder, 13);
		fd_income_composite.bottom = new FormAttachment(100, -10);
		fd_income_composite.left = new FormAttachment(0, 10);
		fd_income_composite.right = new FormAttachment(0, 384);
		formIncome.setVisible(false);
		formIncome.setLayoutData(fd_income_composite);

		formGoal = new Composite(shell, SWT.NONE);
		formGoal.setLayout(new GridLayout(4, false));
		formGoal.setVisible(false);
		FormData fd_goal_composite = new FormData();
		fd_goal_composite.top = new FormAttachment(menuHolder, 13);
		fd_goal_composite.bottom = new FormAttachment(100, -10);
		fd_goal_composite.left = new FormAttachment(0, 10);
		fd_goal_composite.right = new FormAttachment(0, 384);
		formGoal.setLayoutData(fd_goal_composite);

		lblMenu.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, true,
				1, 1));
		lblMenu.setText("Select the item you wish to add:  ");

		try {
			refreshExpenseForm(mc);
			refreshIncomeForm(mc);
			refreshGoalForm(mc);
		} catch (Exception e2) {
			e2.printStackTrace();
		}

		menuCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				System.out.println(menuCombo.getSelectionIndex());
				if (menuCombo.getSelectionIndex() == 0) {
					formGoal.setVisible(false);
					formIncome.setVisible(false);
					formExpense.setVisible(true);
					try {
						refreshExpenseForm(mc);
					} catch (Exception e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
				if (menuCombo.getSelectionIndex() == 1) {
					formGoal.setVisible(false);
					formExpense.setVisible(false);
					formIncome.setVisible(true);
					try {
						refreshIncomeForm(mc);
					} catch (Exception e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
				if (menuCombo.getSelectionIndex() == 2) {
					formIncome.setVisible(false);
					formExpense.setVisible(false);
					formGoal.setVisible(true);
					refreshGoalForm(mc);
				}
			}
		});
		GridData gd_menuCombo = new GridData(SWT.LEFT, SWT.CENTER, true, false,
				1, 1);
		gd_menuCombo.widthHint = 100;
		menuCombo.setLayoutData(gd_menuCombo);
		String[] comboItems = { "Expense", "Income", "Goal" };
		menuCombo.setItems(comboItems);
		menuCombo.select(0);
	}

	// @author U096819H
	public void refreshExpenseForm(final MasterController mc)
			throws TransformerConfigurationException, InstantiationException,
			IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {

		// ---------::: EXPENSE :::---------
		// Title Input
		Label lblTitle = new Label(formExpense, SWT.NONE);
		lblTitle.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblTitle.setText("Title");

		final Text titleExp = new Text(formExpense, SWT.BORDER);
		titleExp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				3, 1));

		// Amount Input
		Label lblAmount = new Label(formExpense, SWT.NONE);
		lblAmount.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblAmount.setText("Amount");

		final Text amountExp = new Text(formExpense, SWT.BORDER);
		amountExp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				3, 1));

		// Category Input
		Label lblCategory = new Label(formExpense, SWT.NONE);
		lblCategory.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblCategory.setText("Category");

		final Combo categoryExp = new Combo(formExpense, SWT.READ_ONLY);
		categoryExp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 3, 1));
		// TO DO: fill combo list with get all categoryTitle
		ArrayList<Category> catList = mc.GetAllCategory();
		String[] catNames = new String[catList.size()];
		for (int i = 0; i < catList.size(); i++) {
			catNames[i] = catList.get(i).getName();
		}
		categoryExp.setItems(catNames);
		categoryExp.select(0);

		// Source Input
		Label lblSource = new Label(formExpense, SWT.NONE);
		lblSource.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblSource.setText("Source");

		final Combo sourceExp = new Combo(formExpense, SWT.READ_ONLY);
		sourceExp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				3, 1));

		Label lblDate = new Label(formExpense, SWT.NONE);
		lblDate.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false,
				1, 1));
		lblDate.setText("Date");
		// TO DO: fill combo list with get all sourceTitle
		ArrayList<Source> sourceList = mc.GetAllSource();
		String[] sourceNames = new String[sourceList.size()];
		for (int i = 0; i < sourceList.size(); i++) {
			sourceNames[i] = sourceList.get(i).getName();
		}
		sourceExp.setItems(sourceNames);
		sourceExp.select(0);

		// date
		final DateTime dateExp = new DateTime(formExpense, SWT.BORDER
				| SWT.DROP_DOWN);
		final String[] recursiveOptions = { "Yearly", "Monthly", "Weekly",
				"Daily" };
		new Label(formExpense, SWT.NONE);
		new Label(formExpense, SWT.NONE);
		new Label(formExpense, SWT.NONE);

		// Recursive Input
		final Button btnRecurExp = new Button(formExpense, SWT.CHECK);
		final Combo recurOptionsExp = new Combo(formExpense, SWT.READ_ONLY);
		recurOptionsExp.setEnabled(false);
		recurOptionsExp.setItems(recursiveOptions);
		recurOptionsExp.select(0);
		btnRecurExp.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (btnRecurExp.getSelection()) {
					recurOptionsExp.setEnabled(true);
				} else {
					recurOptionsExp.setEnabled(false);
				}
			}
		});
		btnRecurExp.setText("Recursive");
		recurOptionsExp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
				false, 1, 1));
		new Label(formExpense, SWT.NONE);
		new Label(formExpense, SWT.NONE);
		new Label(formExpense, SWT.NONE);
		Label lblPeriod = new Label(formExpense, SWT.NONE);
		lblPeriod.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		// End of Form

		Button btnSubmit = new Button(formExpense, SWT.NONE);
		btnSubmit.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseUp(MouseEvent e) {
				// create expense
				try {
					Period recursP;
					if (btnRecurExp.getSelection()) {
						recursP = CashFlow.Period
								.valueOf(recursiveOptions[recurOptionsExp
										.getSelectionIndex()].toUpperCase());
					} else {
						recursP = null;
					}

					// Date Check
					Calendar _date = Calendar.getInstance();
					_date.set(dateExp.getYear(), dateExp.getMonth(),
							dateExp.getDay());
					if (_date.before(Calendar.getInstance())
							|| _date.equals(Calendar.getInstance())) {
						try {
							mc.AddExpense(titleExp.getText(), categoryExp
									.getItem(categoryExp.getSelectionIndex()),
									Double.parseDouble(amountExp.getText()),
									sourceExp.getItem(sourceExp
											.getSelectionIndex()), _date,
									btnRecurExp.getSelection(), recursP, "");
							NotifyPrompt ntp = new NotifyPrompt(formExpense
									.getShell(), 65);
							ntp.open("New expense created.");
							shell.close();
						} catch (NumberFormatException | IllegalInput e1) {
							NotifyPrompt ntp = new NotifyPrompt(formExpense
									.getShell(), 65);
							ntp.open("Error in creating a new expense.");
							e1.printStackTrace();
						}
					} else {
						NotifyPrompt ntp = new NotifyPrompt(formExpense
								.getShell(), 65);
						ntp.open("Invalid date.");
					}
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
		GridData gd_btnSubmit = new GridData(SWT.RIGHT, SWT.CENTER, true,
				false, 1, 1);
		gd_btnSubmit.widthHint = 85;
		btnSubmit.setLayoutData(gd_btnSubmit);
		btnSubmit.setText("Submit");

		Label label_3 = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
		label_3.setLayoutData(new FormData());
	}

	// @author U096819H
	public void refreshIncomeForm(final MasterController mc)
			throws TransformerConfigurationException, InstantiationException,
			IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {

		// ---------::: INCOME :::---------
		// Title Input
		Label lblTitle = new Label(formIncome, SWT.NONE);
		lblTitle.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblTitle.setText("Title");

		final Text titleInc = new Text(formIncome, SWT.BORDER);
		titleInc.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				3, 1));

		// Amount Input
		Label lblAmount = new Label(formIncome, SWT.NONE);
		lblAmount.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblAmount.setText("Amount");

		final Text amountInc = new Text(formIncome, SWT.BORDER);
		amountInc.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				3, 1));

		// Category Input
		Label lblCategory = new Label(formIncome, SWT.NONE);
		lblCategory.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblCategory.setText("Category");

		final Combo categoryInc = new Combo(formIncome, SWT.READ_ONLY);
		categoryInc.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 3, 1));
		// TO DO: fill combo list with get all categoryTitle
		ArrayList<Category> catList = mc.GetAllCategory();
		String[] catNames = new String[catList.size()];
		for (int i = 0; i < catList.size(); i++) {
			catNames[i] = catList.get(i).getName();
		}
		categoryInc.setItems(catNames);
		categoryInc.select(0);

		// Source Input
		Label lblSource = new Label(formIncome, SWT.NONE);
		lblSource.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblSource.setText("Source");

		final Combo sourceInc = new Combo(formIncome, SWT.READ_ONLY);
		sourceInc.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				3, 1));

		Label lblDate = new Label(formIncome, SWT.NONE);
		lblDate.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false,
				1, 1));
		lblDate.setText("Date");
		// TO DO: fill combo list with get all sourceTitle
		ArrayList<Source> sourceList = mc.GetAllSource();
		String[] sourceNames = new String[sourceList.size()];
		for (int i = 0; i < sourceList.size(); i++) {
			sourceNames[i] = sourceList.get(i).getName();
		}
		sourceInc.setItems(sourceNames);
		sourceInc.select(0);

		// date
		final DateTime dateInc = new DateTime(formIncome, SWT.BORDER
				| SWT.DROP_DOWN);
		final String[] recursiveOptions = { "Yearly", "Monthly", "Weekly",
				"Daily" };
		new Label(formIncome, SWT.NONE);
		new Label(formIncome, SWT.NONE);
		new Label(formIncome, SWT.NONE);

		// Recursive Input
		final Button recurInc = new Button(formIncome, SWT.CHECK);
		final Combo recurOptionInc = new Combo(formIncome, SWT.READ_ONLY);
		recurOptionInc.setEnabled(false);
		recurOptionInc.setItems(recursiveOptions);
		recurOptionInc.select(0);
		recurInc.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (recurInc.getSelection()) {
					recurOptionInc.setEnabled(true);
				} else {
					recurOptionInc.setEnabled(false);
				}
			}
		});
		recurInc.setText("Recursive");
		recurOptionInc.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false,
				false, 1, 1));
		new Label(formIncome, SWT.NONE);
		new Label(formIncome, SWT.NONE);
		new Label(formIncome, SWT.NONE);
		Label lblPeriod = new Label(formIncome, SWT.NONE);
		lblPeriod.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		// End of Form

		Button btnSubmit = new Button(formIncome, SWT.NONE);
		btnSubmit.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseUp(MouseEvent e) {
				// create expense
				try {
					Period recursP;
					if (recurInc.getSelection()) {
						recursP = CashFlow.Period
								.valueOf(recursiveOptions[recurOptionInc
										.getSelectionIndex()].toUpperCase());
					} else {
						recursP = null;
					}

					// Date Check
					Calendar _date = Calendar.getInstance();
					_date.set(dateInc.getYear(), dateInc.getMonth(),
							dateInc.getDay());
					System.out.println("::1::" + _date);
					System.out.println("::2::"
							+ Calendar.getInstance().getTime());
					System.out.println("::::::");
					if (_date.before(Calendar.getInstance())
							|| _date.equals(Calendar.getInstance())) {
						try {
							mc.AddIncome(titleInc.getText(), categoryInc
									.getItem(categoryInc.getSelectionIndex()),
									Double.parseDouble(amountInc.getText()),
									sourceInc.getItem(sourceInc
											.getSelectionIndex()), _date,
									recurInc.getSelection(), recursP, "");
							NotifyPrompt ntp = new NotifyPrompt(formIncome
									.getShell(), 65);
							ntp.open("New income created.");
							shell.close();
						} catch (NumberFormatException | IllegalInput e1) {
							NotifyPrompt ntp = new NotifyPrompt(formIncome
									.getShell(), 65);
							ntp.open("Error in creating a new income.");
							e1.printStackTrace();
						}
					} else {
						NotifyPrompt ntp = new NotifyPrompt(formIncome
								.getShell(), 65);
						ntp.open("Invalid date.");
					}
				} catch (InstantiationException | IllegalAccessException
						| JAXBException | ParserConfigurationException
						| SAXException | IOException | TransformerException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
		GridData gd_btnSubmit = new GridData(SWT.RIGHT, SWT.CENTER, true,
				false, 1, 1);
		gd_btnSubmit.widthHint = 85;
		btnSubmit.setLayoutData(gd_btnSubmit);
		btnSubmit.setText("Submit");

		Label label_3 = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
		label_3.setLayoutData(new FormData());
	}

	// @author U096819H
	public void refreshGoalForm(final MasterController mc) {
		System.out.println("::: GOAL");
		// Labels
		Label lblTitle = new Label(formGoal, SWT.NONE);
		lblTitle.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblTitle.setText("Title");

		// input text box
		final Text title_input = new Text(formGoal, SWT.BORDER);
		title_input.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 3, 1));

		Label lblTotalAmount = new Label(formGoal, SWT.NONE);
		lblTotalAmount.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblTotalAmount.setText("Amount");

		final Text amountT_input = new Text(formGoal, SWT.BORDER);
		amountT_input.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 3, 1));

		Label lblComment = new Label(formGoal, SWT.NONE);
		lblComment.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblComment.setText("Comment");

		final Text comment_input = new Text(formGoal, SWT.BORDER);
		comment_input.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 3, 1));

		Label lblStartDate = new Label(formGoal, SWT.NONE);
		lblStartDate.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblStartDate.setText("Start Date");

		final DateTime startDate = new DateTime(formGoal, SWT.BORDER
				| SWT.DROP_DOWN);
		startDate.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false,
				3, 1));

		Label lblEndDate = new Label(formGoal, SWT.NONE);
		lblEndDate.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 1, 1));
		lblEndDate.setText("End Date");

		final DateTime endDate = new DateTime(formGoal, SWT.BORDER
				| SWT.DROP_DOWN);
		endDate.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false,
				3, 1));

		final Button btnActive = new Button(formGoal, SWT.CHECK);
		btnActive.setText("Active ");
		btnActive.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
				false, 3, 1));
		btnActive.setSelection(true);

		Button btnSubmit = new Button(formGoal, SWT.NONE);
		btnSubmit.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseUp(MouseEvent e) {
				// create goal
				try {

					Calendar ed = Calendar.getInstance();
					ed.set(endDate.getYear(), endDate.getMonth(),
							endDate.getDay());
					Calendar sd = Calendar.getInstance();
					sd.set(startDate.getYear(), startDate.getMonth(),
							startDate.getDay());
					if (ed.after(sd)) {
						mc.AddGoal(title_input.getText(), sd, ed,
								Double.parseDouble(amountT_input.getText()), 0,
								comment_input.getText(),
								btnActive.getSelection(), false);

						NotifyPrompt ntp = new NotifyPrompt(
								formGoal.getShell(), 65);
						ntp.open("New Goal Created.");
						shell.close();
					} else {
						NotifyPrompt ntp = new NotifyPrompt(formIncome
								.getShell(), 65);
						ntp.open("Invalid dates. Start date is after end date.");
					}
				} catch (Exception e1) {
					NotifyPrompt ntp = new NotifyPrompt(formGoal.getShell(), 65);
					ntp.open("Error in creating new goal.");
				}
			}
		});
		GridData gd_btnSubmit = new GridData(SWT.RIGHT, SWT.CENTER, true,
				false, 1, 1);
		gd_btnSubmit.widthHint = 85;
		btnSubmit.setLayoutData(gd_btnSubmit);
		btnSubmit.setText("Submit");
	}
}
